# frozen_string_literal: true

require('singleton')
VIDE_CHAR = '-'

CLASSIC_FINAL_MASK = [
  %w[- - - -],
  %w[- - - -],
  %w[- - - -],
  %w[- a a -],
  %w[- a a -]
].freeze

GAMES = {
  :reference => {
    :initial_board => [
      %w[c a a d],
      %w[c a a d],
      %w[e b b f],
      %w[e h i f],
      %w[g - - j]
    ],
    :final_mask => CLASSIC_FINAL_MASK
  },

  :nearly_solved => {
    :initial_board => [
      %w[c b b d],
      %w[c h i d],
      %w[e a a f],
      %w[e a a f],
      %w[g - j -]
    ],
    :final_mask => CLASSIC_FINAL_MASK
  },

  :variant => {
    :initial_board => [
      %w[c a a d],
      %w[c a a d],
      %w[g b b i],
      %w[h k k j],
      %w[- l l -]
    ],
    :final_mask => CLASSIC_FINAL_MASK
  },

  :small => {
    :initial_board => [
      %w[a a i],
      %w[a a -],
      %w[g h -],
      %w[- - -]
    ],
    :final_mask => [
      %w[- - -],
      %w[- - -],
      %w[a a -],
      %w[a a -]
    ]
  }
}.freeze

class Game
  include Singleton

  def self.games
    return GAMES.keys
  end

  attr_reader(
    :game,
    :initial_board,
    :final_mask,
    :vide_char,
    :board_chars,
    :piece_chars
  )

  def initialize
    reset(:reference)
  end

  def reset(game)
    @game = game

    gamespec = GAMES[@game]
    @initial_board = Board.new(gamespec[:initial_board]).freeze
    @final_mask    = PieceMask.new(gamespec[:final_mask]).freeze
    @vide_char     = VIDE_CHAR
    @board_chars   = @initial_board.b.flatten.uniq.freeze
    @piece_chars   = @board_chars - Array[@vide_char]
    @target_char   = (@final_mask.b.flatten.uniq - Array(vide_char)).first.freeze
  end

  def winning?(board)
    return PieceMask.nu(board, @target_char) == @final_mask
  end

  def vide_char?(c)
    return c == @vide_char
  end
end
